#include "fig_background_enemy.h"
#include "fig_player_craft.h"
#include "fighter.h"
#include "fig_enemybullet_master.h"
#include "fig_functions.h"
#include "fig_vars.h"
#include "fig_pickup_manager.h"
#include "fig_sfx_manager.h"


#include "math/facing.h"
#include "num/rand.h"

FIGBackgroundEnemy::FIGBackgroundEnemy(const std::string& Name , 
						const math::Vec2&	Pos,
						float				Speed, 
						float				MoveScaleX,
						float				Rotation, 
						float				Scale,
						int					Layer
						): FIGBackground("",
										 Pos,
										 Speed,
										 MoveScaleX,
										 Rotation,
										 Scale,
										 Layer,
										 ColorfRGBA(1.0f,1.0f,1.0f,1.0f)
										 ),
							FIGLifeObj(),
							m_State(LAUNCHER_STATE_NOT_SHOWNYET),
							m_LaucherType(LAUNCHER_TYPE_2SHOOTS),
							m_bShouldTakeLessDamage(true)
{

	m_LaucherType = MapNameToType(Name);	
	m_Bone.Load(MapTypeToBoneFile(m_LaucherType));
	m_Bone.Reset();
	m_ShootCounter.SetLimit(3.0f);
	m_Rotation = 0;
	m_Life = m_MaxLife = 20;
	m_ExplodeSize = 2.0f;

	m_OringinalX = m_Pos.x;
    m_IsAlive = true;
	m_ExplodSoundSfx = FIGSounds::EXPLOSION_VERYBIG;

	m_OffsetScale = m_MoveScaleX;

	
	

}
	


std::string		FIGBackgroundEnemy::GetBoneFileName()const
{
	return m_Bone.GetFileName();
}
	
void		FIGBackgroundEnemy::Tick(float dt)
{
	

	if(!m_IsAlive && !m_Bone.IsExploding())
		m_IsToDelete = true;
	
	if(m_IsToDelete && !m_Bone.IsExploding())
		return; 	

	if(!m_IsAlive && !m_Bone.IsExploding())
		return;

	m_Pos = math::Vec2(m_OringinalX,m_Pos.y);
	GetForeGroundPos(m_Pos);

	Tick_States(dt);
	FIGBackground::Tick(dt);  
	
	m_Bone.SetPos(m_Pos);
	if(m_State == LAUNCHER_STATE_NOT_SHOWNYET)	
	{
	}
	else
	{
		FIGLifeObj::Tick(dt);	
	
	
		m_Bone.SetRotation(m_Rotation);
		m_Bone.Tick(dt); 
	}
	
	

}

void		FIGBackgroundEnemy::Clear()
{
	FIGBackground::Clear();
	
}


void		FIGBackgroundEnemy::Tick_States(float dt)
{
	switch(m_State)
	{
		case LAUNCHER_STATE_NOT_SHOWNYET:
			Tick_NotShownYet(dt);
		break;
		case LAUNCHER_STATE_FIRST_SHOWN:
			m_State = LAUNCHER_STATE_TRANSFORM;
		break;
		case LAUNCHER_STATE_TRANSFORM:
			Tick_Transform(dt);
		break;
		case LAUNCHER_STATE_ATTACK:
			Tick_Attack(dt);
		break;


	}
}

void		FIGBackgroundEnemy::Tick_NotShownYet(float dt)
{
	math::Vec2 Size =   m_Bone.GetSize() * Fighter::Instance().GetScale();
	if(m_Pos.y > Size.y * 0.35f )
	{
		m_State = LAUNCHER_STATE_FIRST_SHOWN;
		int Difficulty = FIGVars::Instance()->GetInt(FIGVars::VAR_NAMES_DIFFICULTY);
		float ExtraLife =   m_MaxLife *  Difficulty * 0.35f;

		m_Life = m_MaxLife + ExtraLife;
        m_IsAlive = true;
	}
}

void		FIGBackgroundEnemy::Tick_Transform(float dt)
{
	if(m_Bone.TransformForwardTick(dt))
	{
		m_State = LAUNCHER_STATE_ATTACK;
		m_IsReadyToFire = true;
		m_ShootCounter.SetCounter(0.5f);
	}
}

void		FIGBackgroundEnemy::Tick_Attack(float dt)
{
	AimToPlayer(dt);   	
}

void		FIGBackgroundEnemy::Render(const math::Vec2& Offset, const math::Vec2& ShakeOffset, float Scale)
{
	if(!m_IsAlive && !m_Bone.IsExploding())
		return;

	if(m_IsToDelete && !m_Bone.IsExploding())
		return;

	// not reach yet 
	if(m_Pos.y + (m_Bone.GetSize().y*0.5f) < 0 && m_Pos.y + (m_Bone.GetSize().x*0.5f) < 0)
		return;

	// passed already
	if(m_Pos.y - (m_Bone.GetSize().y*0.5f) > 1  && m_Pos.y - (m_Bone.GetSize().x*0.5f) > 1)
		m_IsToDelete = true;

	m_Bone.Render(Offset + ShakeOffset,Scale);
	RenderSFX(Offset + ShakeOffset,Scale);
	
}

void		FIGBackgroundEnemy::AimToPlayer(float dt)
{
	
	math::Vec2 PlayerPos = FIGPlayerCraft::Instance().GetPos();
	float Angle = math::Facing::AngleFromTo(m_Pos , PlayerPos);
		
	FigFunctions::ToDegree(	m_Rotation,
							Angle + 180, 
							45.0f * dt 
							);

		
}

void		FIGBackgroundEnemy::OnShoot()
{
	switch (m_LaucherType)
	{
		
		case LAUNCHER_TYPE_2SHOOTS:
			OnShoot_2();
		break;

		case LAUNCHER_TYPE_3SHOOTS:
			OnShoot_3();
		break;

		case LAUNCHER_TYPE_6SHOOTS:
			OnShoot_6();
		break;	

	}

	m_bShouldTakeLessDamage	= false;
}

bool	FIGBackgroundEnemy::HitTest(FIGBullet* pBullet)
{
	if(m_IsToDelete)
		return false;

	if(!m_IsAlive)
		return false;

	if(m_Life <= 0)
		return false;

	bool b = m_Bone.HitTest(pBullet->GetPos());
	if(b)
	{
		GotDamage(pBullet->GetDamagePower(),pBullet, false);
		pBullet->Kill();
		return true;
	}
		
	return false;
}

bool	FIGBackgroundEnemy::HitTest(const math::Vec2& Point)
{
   if(m_IsToDelete)
		return false;

	if(!m_IsAlive)
		return false;

	if(m_Life <= 0)
		return false;

	bool b = m_Bone.HitTest(Point);
	return b;
}


std::string		FIGBackgroundEnemy::MapTypeToBoneFile(LAUNCHER_TYPE Type)
{										
	switch (Type)
	{
		
		case LAUNCHER_TYPE_2SHOOTS:
		return "transform/weapon_machinegun.lua";

		case LAUNCHER_TYPE_3SHOOTS:
		return "transform/weapon_lasergun.lua";

		case LAUNCHER_TYPE_6SHOOTS:
		return "transform/weapon_shotgun.lua";		

	}

	return "";
}

std::string		FIGBackgroundEnemy::MapTypeToName(LAUNCHER_TYPE Type)
{
	switch (Type)
	{
		
		case LAUNCHER_TYPE_2SHOOTS:
		return "weapon_machinegun";

		case LAUNCHER_TYPE_3SHOOTS:
		return "launcher_laser";

		case LAUNCHER_TYPE_6SHOOTS:
		return "shot_gun";	

		default:
			break;

	}

	return "unknown";
}

FIGBackgroundEnemy::LAUNCHER_TYPE		FIGBackgroundEnemy::MapNameToType(const std::string& TypeName)
{
	for (unsigned int i = 0; i < LAUNCHER_TYPE_COUNT; i++)
		if (strcmpi( MapTypeToName((LAUNCHER_TYPE)i).c_str(), TypeName.c_str() ) == 0)
			return (LAUNCHER_TYPE)i;

	return LAUNCHER_TYPE_UNKNOWN;  	
}


void	FIGBackgroundEnemy::OnShoot_2()
{
	if(!IsInSideScreen())
		return;

	float Rotation = m_Rotation + 180;
	
	math::Vec2 P = FigFunctions::RotateAroundPos( math::Vec2(0,0),
												GetBonePos(0),
												m_Rotation);


	FIGBonePart* pPart = m_Bone.GetBonePartByID(4);
	if(pPart)
		pPart->Shoot(Rotation);

	pPart = m_Bone.GetBonePartByID(5);
	if(pPart)
		pPart->Shoot(Rotation + 180);

	for(int i = 0; i < 2; i++)
	{
		FIGEnemyBulletMaster::Instance().Shoot( 
											this,
											P, 
											FIGEnemyBulletMaster::BULLET_TYPE_LONG_GREEN, 
											FIGBullet::SHOOT_STYLES_SINGLE, 
											Rotation,
											i * 0.1f,
											false,
											NULL
											);
	}


	
	P = FigFunctions::RotateAroundPos( math::Vec2(0,0),
												GetBonePos(1),
												m_Rotation);

	for(int i = 0; i < 2; i++)
	{
		FIGEnemyBulletMaster::Instance().Shoot( 
											this,
											P, 
											FIGEnemyBulletMaster::BULLET_TYPE_LONG_GREEN, 
											FIGBullet::SHOOT_STYLES_SINGLE, 
											Rotation,
											i * 0.1f,
											false,
											NULL
											);
	}

	
}


void	FIGBackgroundEnemy::OnShoot_3()
{

	if(!IsInSideScreen())
		return;

	float Rotation = m_Rotation + 180;
	
	math::Vec2 P = FigFunctions::RotateAroundPos( math::Vec2(0,0),
												GetBonePos(0),
												m_Rotation);


	FIGBonePart* pPart = m_Bone.GetBonePartByID(4);
	if(pPart)
		pPart->Shoot(Rotation + 180);

	

	for(int i = 0; i < 1; i++)
	{
		FIGEnemyBulletMaster::Instance().Shoot( 
											this,
											P, 
											FIGEnemyBulletMaster::BULLET_TYPE_LONG_YELLOW, 
											FIGBullet::SHOOT_STYLES_SINGLE, 
											Rotation,
											i * 0.1f,
											false,
											NULL
											);
	}


	
	P = FigFunctions::RotateAroundPos( math::Vec2(0,0),
												GetBonePos(1),
												m_Rotation);

	for(int i = 0; i < 1; i++)
	{
		FIGEnemyBulletMaster::Instance().Shoot( 
											this,
											P, 
											FIGEnemyBulletMaster::BULLET_TYPE_LONG_RED, 
											FIGBullet::SHOOT_STYLES_SINGLE, 
											Rotation,
											i * 0.1f,
											false,
											NULL
											);
	}

	P = FigFunctions::RotateAroundPos( math::Vec2(0,0),
												GetBonePos(2),
												m_Rotation);

	for(int i = 0; i < 1; i++)
	{
		FIGEnemyBulletMaster::Instance().Shoot( 
											this,
											P, 
											FIGEnemyBulletMaster::BULLET_TYPE_LONG_YELLOW, 
											FIGBullet::SHOOT_STYLES_SINGLE, 
											Rotation,
											i * 0.1f,
											false,
											NULL
											);
	}

}


void	FIGBackgroundEnemy::OnShoot_6()
{
	if(!IsInSideScreen())
		return;

	float Rotation = m_Rotation + 180;
	
	math::Vec2 P = FigFunctions::RotateAroundPos( math::Vec2(0,0),
												GetBonePos(0),
												m_Rotation);


	FIGBonePart* pPart = m_Bone.GetBonePartByID(4);
	if(pPart)
		pPart->Shoot(Rotation + 180);

	pPart = m_Bone.GetBonePartByID(5);
	if(pPart)
		pPart->Shoot(Rotation + 180);

	for(int i = 0; i < 3; i++)
	{
		FIGEnemyBulletMaster::Instance().Shoot( 
											this,
											P, 
											FIGEnemyBulletMaster::BULLET_TYPE_CIRCLE_DOUBLELAYER, 
											FIGBullet::SHOOT_STYLES_SINGLE, 
											Rotation,
											i * 0.1f,
											false,
											NULL
											);
	}


	
	P = FigFunctions::RotateAroundPos( math::Vec2(0,0),
												GetBonePos(1),
												m_Rotation);

	for(int i = 0; i < 3; i++)
	{
		FIGEnemyBulletMaster::Instance().Shoot( 
											this,
											P, 
											FIGEnemyBulletMaster::BULLET_TYPE_CIRCLE_DOUBLELAYER, 
											FIGBullet::SHOOT_STYLES_SINGLE, 
											Rotation,
											i * 0.1f,
											false,
											NULL
											);
	}
}

math::Vec2		FIGBackgroundEnemy::GetBonePos(int ID)
{
	const math::Vec2 Offset = Fighter::Instance().GetOffset() * m_MoveScaleX * Fighter::Instance().GetScale();
	return m_Bone.GetPosByWayPoint(ID);//	- Offset;
}

void		FIGBackgroundEnemy::GetForeGroundPos(math::Vec2& Output)
{
	// to make this one foreground obj to calculate things easier
	// we need to move opposite of the offset
	Output.y = m_Pos.y;
	Output.x = m_Pos.x - ( Fighter::Instance().GetOffset().x * m_MoveScaleX);
}

void		FIGBackgroundEnemy::OnDie()
{
	FIGLifeObj::OnDie();
	m_Bone.Explode(this);

	if(num::RAND32::Instance().RandInt(1,80) == 1)
	{
		if(num::RAND32::Instance().RandInt(1,7) == 1)
			FIGPickupManager::Instance().Spawn(FIGPickup::PICKUP_TYPE_NUKE,m_Pos);
		else if(num::RAND32::Instance().RandInt(1,7) == 2)
			FIGPickupManager::Instance().Spawn(FIGPickup::PICKUP_TYPE_ROKET_SHOOT,m_Pos);	
		else if(num::RAND32::Instance().RandInt(1,7) == 3)
			FIGPickupManager::Instance().Spawn(FIGPickup::PICKUP_TYPE_HEALTH,m_Pos);
		else if(num::RAND32::Instance().RandInt(1,7) == 4)
			FIGPickupManager::Instance().Spawn(FIGPickup::PICKUP_TYPE_WEAPON_BLUE,m_Pos);
		else if(num::RAND32::Instance().RandInt(1,7) == 5)
			FIGPickupManager::Instance().Spawn(FIGPickup::PICKUP_TYPE_WEAPON_RED,m_Pos);
		else if(num::RAND32::Instance().RandInt(1,7) == 6)
			FIGPickupManager::Instance().Spawn(FIGPickup::PICKUP_TYPE_WEAPON_GREEN,m_Pos);
		else if(num::RAND32::Instance().RandInt(1,7) == 7)
			FIGPickupManager::Instance().Spawn(FIGPickup::PICKUP_TYPE_SHIELD,m_Pos);
		

	}
	else
		FIGPickupManager::Instance().Spawn(FIGPickup::PICKUP_TYPE_STAR,m_Pos);

	
}


void		FIGBackgroundEnemy::GotDamage(float Amount,FIGBullet* pBullet,bool Force)
{
	if(!Force && m_bShouldTakeLessDamage)
		Amount = Amount * 0.005f;

	FIGLifeObj::GotDamage(Amount,pBullet,Force);

}

